今天要來介紹如何透過使用Hive來對HBase table進行查詢。由前面的HBase篇章已經知道HBase本身是沒有提供SQL查詢的介面與功能,
只能依賴其他的工具,例如 Phoenix 或是本篇要介紹的 Hive。
而由於 Hive 可以使用Hive CLI且安裝簡易,不用啟動service就可以使用,所以受到不少使用者使用,接下來就來介紹Hive如何與HBase整合吧!
開始之前要注意一件事情:
Hive 1.x版本目前只支援HBase 0.98.x與之前的版本。而HBase 1.x之後的版本,請使用Hive 2.x之後的版本。
假設你想在Hive 1.x使用HBase 1.x,那就要自行重新編譯Hive的原始碼。
好的,假設我們已經有一個HBase叢集,且下載Hive 2.1.1版本,Hive CLI環境也已經設定完成,接著只要在進行修改hive-site.xml
,即可透過Hive CLI使用SQL語法對HBase進行操作。
開啟hive-site.xml
並加入下面的設定值:
<property>
<name>hbase.zookeeper.quorum</name>
<value>{zookeeper host}</value>
<description>使用HBase內建的zookeeper則指定為HBase master的hostname,若是使用外部且多台zookeeper,請用,分隔。
</description>
</property>
<property>
<name>hive.aux.jars.path</name>
<value>${HIVE_HOME}/lib/hive-hbase-handler-2.1.1.jar,
${HIVE_HOME}lib/hbase-server-1.1.1.jar,
${HIVE_HOME}/lib/zookeeper-3.4.6.jar,
${HIVE_HOME}/lib/guava-14.0.1.jar
</value>
</property>
設定完畢後,重新啟動Hive CLI即可開始透過 SQL 操作HBase Table啦!
其實Hive與HBase整合非常簡單與方便,下面會介紹兩種使用情境,透過Hive CLI建立HBase table的語法,分別是:
假設HBase上面尚未有任何table,我們可以使用Hive SQL來建立一個
#啟動hive
hive
輸入下面語法:
CREATE TABLE new_hbase_table(key int, value string)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf1:val")
TBLPROPERTIES ("hbase.table.name" = "new_table", "hbase.mapred.output.outputtable" = "new_table");
#說明
hbase.columns.mapping : 欄位對應。必須與hive table的順序相對應。例如:key對應到:key,value對應到cf:value,id對應到cf:id。
hbase.table.name : HBase table name。若沒有指定,預設hive table name會與hbase table name相同。
hbase.mapred.output.outputtable : HBase table name,非必要設定。若需要在Hive使用insert的指令,則需要指定。
完成後可以使用hbase shell
進入查詢,此時可以發現new_table已經被建立,要注意的是,透過這個語法所建立的HBase table,當在Hive CLI使用drop table指令時,HBase table同時會被刪除。
只要進入Hive CLI後,對已經存在的HBase table 建立Hive external table,定義欄位與型別即可。
假設我們有一個HBase table hbase_table
,並且使用hbase shell
的put
指令新增資料:
put 'hbase_table', 'rk_1', 'cf:value', '65535'
put 'hbase_table', 'rk_2', 'cf:value', '111'
put 'hbase_table', 'rk_3', 'cf:value', '9487'
put 'hbase_table', 'rk_3', 'cf:id', 'John'
可以看出來這個HBase table的擁有column family: cf
。接下來在Hive CLI內使用下面的指令:
#啟動hive
hive
#Create Hive table on HBase
create external table hbase_table(key string, value string, id string)
stored by 'org.apache.hadoop.hive.hbase.hbasestoragehandler'
with serdeproperties ("hbase.columns.mapping" = ":key,cf:value,cf:id") tblproperties ("hbase.table.name" = "hbase_table" "hbase.mapred.output.outputtable" = "hbase_table");
當hive table建立完畢,該資料表會長成這樣:
key | id | value |
---|---|---|
rk_1 | 65535 | |
rk_2 | 111 | |
rk_3 | John | 9487 |
透過create external table
指令建立的hive table,當使用drop table指令時,原本的HBase table是不會被刪除的。
當hive table建立完成後,我們就可以透過hive sql語法來對HBase進行操作,語法使用可以參考"Apache Hive SQL 基礎教學"這一篇文章。要注意的是,透過hive sql對HBase進行查詢時,若是使用join語法,會觸發mapreduce的job執行,當HBase資料量龐大region數量很多時,mapreduce運作時會開啟大量map與HBase進行溝通,此時HBase會受到大量的RPC連線,有機會影響到HBase其他的AP的運作,甚至導致HBase regionserver shutdown ,請務必小心使用。
看完了Hive 與 HBase的整合應用教學,接下來要來介紹如何使用hiveserver2囉。
請問hive跟hbase整合並創一個表之後我在hbase新增資料但是在hive沒有同步新增資料是哪邊出錯了?(沒有跳錯誤訊息)
我有試過一次您的方法有成功,但之後再試一次就沒有同步,但兩邊的表都有建立
還有我想順便問一下有沒有辦法整合表之後在Hbase新增超過hive欄位數量的列嗎?
因為我有資料是欄位不固定的,我想在Hbase的某個列族底下創很多個列來放這些資料
然後在hive查詢這些資料
Hi,
請問hive跟hbase整合並創一個表之後我在hbase新增資料但是在hive沒有同步新增資料是哪邊出錯了?(沒有跳錯誤訊息)
要注意一下您在hbase新增的資料所屬的column family是否有出現在建立hive 的語法內:
create external table hbase_table(key string, value string, id string)
stored by 'org.apache.hadoop.hive.hbase.hbasestoragehandler'
with serdeproperties ("hbase.columns.mapping" = ":key,cf:value,cf:id") tblproperties ("hbase.table.name" = "hbase_table" "hbase.mapred.output.outputtable" = "hbase_table");
以上節錄的語法,這個hive table只認得hbase table的:key
,cf:value
,cf:id
這三個欄位,其他的一率不會出現在hive table內喔。
還有我想順便問一下有沒有辦法整合表之後在Hbase新增超過hive欄位數量的列嗎?
因為我有資料是欄位不固定的,我想在Hbase的某個列族底下創很多個列來放這些資料
然後在hive查詢這些資料
這邊說明一下hive 與 hbase(或者其他可以整合的儲存層)整合的概念,透過hive建立的表(table)並不是一個真實的表,而是一個敘述稱之為metadata, 而hiveQL就會根據這個metadata去hbase(或者其他可以整合的儲存層)相對應的欄位讀取資料。
整合主要的重點是,任何操作都要透過hive,否則hive不會知道使用者在hbase做了什麼事,也沒辦法去查詢使用者偷偷繞過hive 所新增的欄位
與該欄位的資料。
回到問題,hbase欄位不固定的情況,據我所知hive 2.1.1版本為止,hive沒有提供與hbase更新metadata的功能,所以當hbase端新增了一個hive table內沒有的欄位時,需要修改(alter)或者重新建立的一個hive mapping到hbase的table.
如果您有找到其他的做法也可以留言,互相教學相長 :D
请问, Hive 关联 HBase 默认自动创建表这种情况:
默认创建的 HBase 表为 1 个分区
如何让这种情况下, 自动创建的表可以预分裂, 如果语法支持, 请问如何指定相关属性, 譬如 start-end key 等信息, 谢谢!
默认创建的 HBase 表为 1 个分区
如何让这种情况下, 自动创建的表可以预分裂, 如果语法支持, 请问如何指定相关属性, 譬如 start-end key 等信息, 谢谢!
您的意思是在建立hive 與hbase的mapping table時, 如何設定hive partition對應到hbase 的region?
感谢回复, 假定一个分区, 关联的 rowkey 为 000-fff, 我想让这些数据感谢回复, 假定一个分区或多个分区, 所有数据的 rowkey 为 000-fff, 我想让这些数据均匀的分布在 100 个 region 中. 预分裂的话, 在 HBase 中创建表的语法为 CREATE 'table_name', {NAME=>'columnfamily'}, {SPLITS=>['01f', '03e', '07c'...'fdd','ffc']}. 那么要想自动让 HIVE 也创建类似预分裂 100 个分区的 table 该如何操作.
我现在遇到这个问题了, 因为集群关闭了自动分裂, 所以为了性能, 必须提前预分裂. 现在 workaround 是先手动建立 HBase 表, 再创建 Hive 外部表. 现在核心问题就是找不到一种方式, 能让 Hive 自动创建的表也能预分裂指定数量, 并指定分区rowkey边界.
搜尋了一下apache hive jira, 目前沒有看到相關的討論, 我想現階段應該是無法讓hive 的partition指定到hbase的region。
在 HDP 3.0 中, 也就是HIVE3.0之后的版本, 有些语法发生了变化, 如:
A change to Hive in HDP 3.0 is that all StorageHandlers must be marked as “external”. There is no such thing as an non-external table created by a StorageHandler. If the corresponding HBase table exists when the Hive table is created, it will mimic the HDP 2.x semantics of an “external” table. If the corresponding HBase table does not exist when the Hive table is created, it will mimic the HDP 2.x semantics of a non-external table (e.g. the HBase table is dropped when the Hive table is dropped). -- from https://docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.4/hbase-data-access/content/hdag_hbase_hive_integration_example.html